package com.itlong.cloud.property.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.itlong.cloud.POJO.DTO.property.*;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.miniprogram.MiniProgramPassRoomListVO;
import com.itlong.cloud.POJO.VO.property.PropertyProjectMinAvaliableRoomInfoVO;
import com.itlong.cloud.POJO.VO.property.PropertyProjectRoomInfoVO;
import com.itlong.cloud.POJO.VO.property.PropertyProjectRoomSimpleInfoExVO;
import com.itlong.cloud.POJO.VO.property.PropertyProjectRoomSimpleInfoVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.app.dao.IAppRoomDao;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.enumerate.CloudElevatorChangeBusinessEnum;
import com.itlong.cloud.enumerate.CloudEntranceChangeBusinessEnum;
import com.itlong.cloud.enumerate.DataStatusEnum;
import com.itlong.cloud.enumerate.SmartCommunityEnum;
import com.itlong.cloud.property.dao.IPropertyRoomInfoDao;
import com.itlong.cloud.property.service.IPropertyRoomInfoService;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <desc>
 *      房屋信息处理接口实现.
 * </desc>
 *
 * @createDate 2017-09-28
 */
@Service
public class PropertyRoomInfoServiceImpl implements IPropertyRoomInfoService {


    private final IPropertyRoomInfoDao iPropertyRoomInfoDao; //房屋信息数据库访问对象

    private final MessageSender messageSender;  //RabbitMQ发送者

    @Autowired
    IAppRoomDao iAppRoomDao;
    @Autowired
    public PropertyRoomInfoServiceImpl(IPropertyRoomInfoDao iPropertyRoomInfoDao,MessageSender messageSender) {
        this.iPropertyRoomInfoDao = iPropertyRoomInfoDao;
        this.messageSender = messageSender;
    }

    /**
     * <desc>
     *      保存单个房间信息
     * </desc>
     *
     * @param propertyProjectSaveRoomInfoDTO 保存房间信息数据传输对象
     * @return 受影响的行数
     * @author LouisLewis
     * @createDate 2017-09-29
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer saveRoomInfo(PropertyProjectSaveRoomInfoDTO propertyProjectSaveRoomInfoDTO) throws Exception {

        //组装单元信息数据库实体对象
        RoomInfoPO roomInfoPO = getRoomInfoBySaveDTO(propertyProjectSaveRoomInfoDTO);

        //将单元信息实体对象保存到数据库(事务保护)
        int intRes  = this.saveRoomInfoToDB(roomInfoPO);

        //添加单个房间时，无条件更新云对讲设备（即使项目没有云对讲，消费者会自行过滤）
        JSONArray jsonArray = new JSONArray();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("roomId",roomInfoPO.getRoomId());
        jsonArray.add(jsonObject);
        //云对讲
        DeviceBusinessChangeLogPO deviceBusinessChangeLogPO
                = new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM,jsonArray,roomInfoPO.getProjectId());
        List<DeviceBusinessChangeLogPO> deviceBusinessChangeLogPOS = new ArrayList<>();
        deviceBusinessChangeLogPOS.add(deviceBusinessChangeLogPO);
        JSONObject dataJs = new JSONObject();
        dataJs.put("data",deviceBusinessChangeLogPOS);
        messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
        //云电梯
        DeviceBusinessElevatorChangeLogPO deviceBusinessElevatorChangeLogPO
                = new DeviceBusinessElevatorChangeLogPO(roomInfoPO.getProjectId(),
                CloudElevatorChangeBusinessEnum.PUSH_ROOM_PWD,jsonArray.toJSONString());
        List<DeviceBusinessElevatorChangeLogPO> deviceElevatorChangeLogPOS = new ArrayList<>();
        deviceElevatorChangeLogPOS.add(deviceBusinessElevatorChangeLogPO);
        dataJs.put("data",deviceElevatorChangeLogPOS);
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                JsonUtil.toJSON(dataJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
        // 云门禁
        List<DeviceBusinessEntranceChangeLogPO> changeEntranceLogPOS = new ArrayList<>();
        changeEntranceLogPOS.add(new DeviceBusinessEntranceChangeLogPO(CloudEntranceChangeBusinessEnum.PUSH_ROOM_PWD, jsonArray, roomInfoPO.getProjectId()));
        dataJs.put("data", changeEntranceLogPOS);
        //发送云门禁指令
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                JSON.toJSONString(dataJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
        );
        return intRes;

    }

    /**
     * <desc>
     *      保存单个房间信息到数据库
     * </desc>
     *
     * @param roomInfoPO 房间信息
     * @return 受影响的行数
     * @author LouisLewis
     * @createDate 2017-09-29
     */
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer saveRoomInfoToDB(RoomInfoPO roomInfoPO) throws Exception{
        //将单元信息实体对象保存到数据库
        int intRes  = iPropertyRoomInfoDao.save(SqlUtil.durableData(roomInfoPO, PlatformConstants.TABLE_SAVE));

        return intRes;
    }

    /**
     * <desc>
     *      修改房屋信息【根据房屋Id（RoomId）】
     * </desc>
     *
     * @param propertyProjectUpdateRoomInfoDTO 修改房屋信息数据传输对象
     * @return 受影响的行数
     * @author LouisLewis
     * @createDate 2017-09-30
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer updateRoomInfo(PropertyProjectUpdateRoomInfoDTO propertyProjectUpdateRoomInfoDTO) throws Exception {
        RoomInfoPO roomInfoPO = new RoomInfoPO();
        BeanUtils.copyProperties(propertyProjectUpdateRoomInfoDTO, roomInfoPO);
        roomInfoPO.setProjectId(null); //不允许更新项目编号
        roomInfoPO.setBuildId(null); //不允许更新楼栋Id
        roomInfoPO.setUnitId(null);//不允许更新单元编号
        roomInfoPO.setRoomNum(null); //不允许更新房间编号
        roomInfoPO.setCreateTime(null); //不允许更新创建时间
        roomInfoPO.setUpdateTime(new Date());

        //更新房屋信息到数据库（事务保护）
        int intRes = this.updateRoomInfoToDB(roomInfoPO,propertyProjectUpdateRoomInfoDTO);

        //如果修改了正背门,更新权限
        if (iPropertyRoomInfoDao.checkLiftDoorType(propertyProjectUpdateRoomInfoDTO.getRoomId(),propertyProjectUpdateRoomInfoDTO.getLiftDoorType()) > 0) {
            Date date = new Date();
            TimeTaskAuthDeviceAddressInfoPO deviceAddrPO = new TimeTaskAuthDeviceAddressInfoPO(propertyProjectUpdateRoomInfoDTO.getProjectId(),
                    propertyProjectUpdateRoomInfoDTO.getLoginUserId(), propertyProjectUpdateRoomInfoDTO.getUnitId(), DataStatusEnum.NORMAL.getType(), date, date);
            deviceAddrPO.setDeviceUniques(iPropertyRoomInfoDao.getDeviceUniqueByUnit(propertyProjectUpdateRoomInfoDTO.getUnitId()));
            iPropertyRoomInfoDao.save(SqlUtil.durableData(deviceAddrPO, PlatformConstants.TABLE_SAVE));

            List<DeviceBusinessChangeLogPO> changes = new ArrayList<>();
            List<DeviceBusinessElevatorChangeLogPO> elevatorChanges = new ArrayList<>();
            List<DeviceBusinessEntranceChangeLogPO> entranceChanges = new ArrayList<>();
            List<Map<String, Object>> roomList = new ArrayList<>();
            Map<String, Object> roomMap = new HashMap<>();
            roomMap.put("roomId", propertyProjectUpdateRoomInfoDTO.getRoomId());
            roomList.add(roomMap);
            //推送房间更新消息
            DeviceBusinessChangeLogPO po = new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM, JsonUtil.toJSON(roomList), propertyProjectUpdateRoomInfoDTO.getProjectId());
            changes.add(po);
            DeviceBusinessElevatorChangeLogPO elevatorPo = new DeviceBusinessElevatorChangeLogPO(propertyProjectUpdateRoomInfoDTO.getProjectId(), CloudElevatorChangeBusinessEnum.PUSH_ROOM_PWD, JsonUtil.toJSON(roomList));
            elevatorChanges.add(elevatorPo);
            DeviceBusinessEntranceChangeLogPO entrancePO = new DeviceBusinessEntranceChangeLogPO(propertyProjectUpdateRoomInfoDTO.getProjectId(), CloudEntranceChangeBusinessEnum.PUSH_ROOM_PWD, JsonUtil.toJSON(roomList));
            entranceChanges.add(entrancePO);
            JSONObject dataJs = new JSONObject();
            dataJs.put("data", changes);
            //发送云对讲业务指令
            messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                    JsonUtil.toJSON(dataJs),
                    RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
            dataJs.put("data", elevatorChanges);
            //推送云电梯房间信息
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                    JsonUtil.toJSON(dataJs),
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
            //发送云门禁指令
            dataJs.put("data", entranceChanges);
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                    JSON.toJSONString(dataJs),
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
            );

            //房屋正背门属性发生变化时，则需要将房屋下的有人脸的用户权限信息同步至人脸识别系统
            List<String> userIdList = iPropertyRoomInfoDao.getFaceInfoByRoomId(propertyProjectUpdateRoomInfoDTO.getRoomId(),propertyProjectUpdateRoomInfoDTO.getProjectId());
            if(userIdList!=null && userIdList.size()>0 && iPropertyRoomInfoDao.isStartFaceByProjectId(propertyProjectUpdateRoomInfoDTO.getProjectId())>0){
                //发送C#人脸识别用户权限变更增量推送指令,先进行持久化，再由定时任务统一去处理 只有设备禁用启用时deviceUnique才不为空
                SmartCardFaceTimePullInfoPO timePullInfoPO = new SmartCardFaceTimePullInfoPO();
                timePullInfoPO.setPullId(LogicIdUtil.bussinessId());
                timePullInfoPO.setProjectId(propertyProjectUpdateRoomInfoDTO.getProjectId());
                timePullInfoPO.setDeviceUniqueInfo("");
                timePullInfoPO.setSyncStatus(1);
                timePullInfoPO.setUserIdInfo(Joiner.on(",").join(userIdList));
                timePullInfoPO.setStatus(1);
                //由于权限更新需要一分钟，故此处为了保证权限最新故90秒后再进行定时任务下发增量数据
                timePullInfoPO.setAllowSyncTime(DateUtil.addSecond(new Date(), 310));
                timePullInfoPO.setCreateTime(new Date());
                iPropertyRoomInfoDao.save(SqlUtil.durableData(timePullInfoPO,PlatformConstants.TABLE_SAVE));
            }

        }

        //修改单个房间时，可能更新云对讲设备
        if (propertyProjectUpdateRoomInfoDTO.getNeedNotifyIntercom()){
            JSONArray jsonArray = new JSONArray();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("roomId",roomInfoPO.getRoomId());
            jsonArray.add(jsonObject);
            JSONObject dataJs = new JSONObject();

            if(iPropertyRoomInfoDao.checkLiftDoorType(propertyProjectUpdateRoomInfoDTO.getRoomId(),propertyProjectUpdateRoomInfoDTO.getLiftDoorType()) == 0){
                //云对讲
                DeviceBusinessChangeLogPO deviceBusinessChangeLogPO
                        = new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM,jsonArray,propertyProjectUpdateRoomInfoDTO.getProjectId());
                List<DeviceBusinessChangeLogPO> deviceBusinessChangeLogPOS = new ArrayList<>();
                deviceBusinessChangeLogPOS.add(deviceBusinessChangeLogPO);

                dataJs.put("data",deviceBusinessChangeLogPOS);
                messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                        JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                        RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
            }

            //云电梯
            DeviceBusinessElevatorChangeLogPO deviceBusinessElevatorChangeLogPO
                    = new DeviceBusinessElevatorChangeLogPO(roomInfoPO.getProjectId(),
                    CloudElevatorChangeBusinessEnum.PUSH_ROOM_PWD,jsonArray.toJSONString());
            List<DeviceBusinessElevatorChangeLogPO> deviceElevatorChangeLogPOS = new ArrayList<>();
            deviceElevatorChangeLogPOS.add(deviceBusinessElevatorChangeLogPO);
            dataJs.put("data",deviceElevatorChangeLogPOS);
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                    JsonUtil.toJSON(dataJs),
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
        }
        return intRes;
    }

    /**
     * <desc>
     *      房屋二维码授权
     * </desc>
     *
     * @return MessageVO 受影响行数
     * @author wangzhi
     * @createDate 2019/09/27
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer qrCodeAuth(PropertyRoomQrCodeAuthDTO propertyRoomQrCodeAuthDTO) throws Exception {
        Date nowTime = new Date();
        RoomInfoPO roomInfoPO = new RoomInfoPO();
        roomInfoPO.setRoomId(propertyRoomQrCodeAuthDTO.getRoomId());
        roomInfoPO.setChargeMode(propertyRoomQrCodeAuthDTO.getChargeMode());
        if (propertyRoomQrCodeAuthDTO.getChargeMode() == 1) {
            PropertyRoomQrcodeBatchRecordPO propertyRoomQrcodeBatchRecordPO = new PropertyRoomQrcodeBatchRecordPO();
            propertyRoomQrcodeBatchRecordPO.setQrcodeBatchRecordId(LogicIdUtil.bussinessId());
            propertyRoomQrcodeBatchRecordPO.setRoomId(propertyRoomQrCodeAuthDTO.getRoomId());
            PropertyRoomQrcodeBatchRecordPO roomQrCodeBatch = iPropertyRoomInfoDao.getRoomQrCodeBatch(propertyRoomQrCodeAuthDTO.getRoomId());
            if (roomQrCodeBatch != null && roomQrCodeBatch.getId() != null) {
                propertyRoomQrcodeBatchRecordPO.setBatch(roomQrCodeBatch.getBatch() + 1);
            } else {
                propertyRoomQrcodeBatchRecordPO.setBatch(1);
            }
            propertyRoomQrcodeBatchRecordPO.setPayCount(StringHandlerUtil.strToIntDef(propertyRoomQrCodeAuthDTO.getUsableTimes(), 0));
            propertyRoomQrcodeBatchRecordPO.setCount(StringHandlerUtil.strToIntDef(propertyRoomQrCodeAuthDTO.getUsableTimes(), 0));
            propertyRoomQrcodeBatchRecordPO.setUsableCount(StringHandlerUtil.strToIntDef(propertyRoomQrCodeAuthDTO.getUsableTimes(), 0));
            propertyRoomQrcodeBatchRecordPO.setStatus(DataStatusEnum.NORMAL.getType());
            propertyRoomQrcodeBatchRecordPO.setCreateTime(nowTime);
            propertyRoomQrcodeBatchRecordPO.setUpdateTime(nowTime);
            iPropertyRoomInfoDao.save(SqlUtil.durableData(propertyRoomQrcodeBatchRecordPO, PlatformConstants.TABLE_SAVE));
        }
        if (propertyRoomQrCodeAuthDTO.getChargeMode() == 2) {
            SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.DATE_FORMAT_TYPE1);
            roomInfoPO.setEndTime(sdf.parse(propertyRoomQrCodeAuthDTO.getEndTime()));
        }
        roomInfoPO.setUpdateTime(nowTime);
        //推送黑名单更新数据
        List<DeviceBusinessChangeLogPO> changes = new ArrayList<>();
        List<DeviceBusinessElevatorChangeLogPO> elevatorChanges = new ArrayList<>();
        List<DeviceBusinessEntranceChangeLogPO> entranceChanges = new ArrayList<>();
        Map<String,Object> blackList = new HashMap<>();
        blackList.put("projectId", propertyRoomQrCodeAuthDTO.getProjectId());
        blackList.put("roomId", propertyRoomQrCodeAuthDTO.getRoomId());
        DeviceBusinessChangeLogPO po = new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_BLACK_LIST, JsonUtil.toJSON(blackList), propertyRoomQrCodeAuthDTO.getProjectId());
        changes.add(po);
        DeviceBusinessElevatorChangeLogPO elevatorPo = new DeviceBusinessElevatorChangeLogPO(propertyRoomQrCodeAuthDTO.getProjectId(), CloudElevatorChangeBusinessEnum.PUSH_BLACK_LIST, JsonUtil.toJSON(blackList));
        elevatorChanges.add(elevatorPo);
        DeviceBusinessEntranceChangeLogPO entrancePO = new DeviceBusinessEntranceChangeLogPO(propertyRoomQrCodeAuthDTO.getProjectId(), CloudEntranceChangeBusinessEnum.PUSH_BLACK_LIST, JsonUtil.toJSON(blackList));
        entranceChanges.add(entrancePO);
        JSONObject pushJs = new JSONObject();
        pushJs.put("data", changes);
        //发送云对讲业务指令
        messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE, JsonUtil.toJSON(pushJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE, RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
        pushJs.put("data", elevatorChanges);
        //推送云电梯业务指令
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                JsonUtil.toJSON(pushJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
        //发送云门禁业务指令
        pushJs.put("data", entranceChanges);
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                JSON.toJSONString(pushJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
        );
        return iPropertyRoomInfoDao.update(SqlUtil.durableData(roomInfoPO, PlatformConstants.TABLE_UPDATE));
    }

    /**
     * <desc>
     *      获取房间剩余次数
     * </desc>
     *
     * @return MessageVO 受影响行数
     * @author Qiang.S
     * @createDate 2020/07/16
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public String getRoomLastCountByRoomId(String roomId) throws Exception {
        Set<String> roomIds = new HashSet<>();
        roomIds.add(roomId);
        List<Map<String, Object>> lastCount = iAppRoomDao.getRoomLastCountByRoomId(roomIds);
        if (lastCount != null && lastCount.size() > 0) {
            return lastCount.get(0).get("usableCount") == null? "0" : lastCount.get(0).get("usableCount").toString();
        }
        return "0";
    }

    /**
     * <desc>
     *      共享电梯线下缴费
     * </desc>
     *
     * @param paymentRecordDTO
     * @author Qiang.S
     * @createDate 2020/07/16
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public void qrCodeAuthForNew(PaymentRecordDTO paymentRecordDTO) throws Exception {
        Date nowTime = new Date();
        RoomInfoPO roomInfoPO = new RoomInfoPO();
        roomInfoPO.setRoomId(paymentRecordDTO.getRoomId());
        roomInfoPO.setChargeMode(1);
        PropertyRoomQrcodeBatchRecordPO propertyRoomQrcodeBatchRecordPO = new PropertyRoomQrcodeBatchRecordPO();
        propertyRoomQrcodeBatchRecordPO.setQrcodeBatchRecordId(LogicIdUtil.bussinessId());
        propertyRoomQrcodeBatchRecordPO.setRoomId(paymentRecordDTO.getRoomId());
        PropertyRoomQrcodeBatchRecordPO roomQrCodeBatch = iPropertyRoomInfoDao.getRoomQrCodeBatch(paymentRecordDTO.getRoomId());
        int usableCount = 0;
        if (roomQrCodeBatch != null && roomQrCodeBatch.getId() != null) {
            propertyRoomQrcodeBatchRecordPO.setBatch(roomQrCodeBatch.getBatch() + 1);
            usableCount = roomQrCodeBatch.getUsableCount();
        } else {
            propertyRoomQrcodeBatchRecordPO.setBatch(1);
        }
        propertyRoomQrcodeBatchRecordPO.setPayCount(StringHandlerUtil.strToIntDef(paymentRecordDTO.getPaymentCount(), 0));
        propertyRoomQrcodeBatchRecordPO.setCount(StringHandlerUtil.strToIntDef(paymentRecordDTO.getPaymentCount(), 0)+usableCount);
        propertyRoomQrcodeBatchRecordPO.setUsableCount(StringHandlerUtil.strToIntDef(paymentRecordDTO.getPaymentCount(), 0)+usableCount);
        propertyRoomQrcodeBatchRecordPO.setStatus(DataStatusEnum.NORMAL.getType());
        propertyRoomQrcodeBatchRecordPO.setCreateTime(nowTime);
        propertyRoomQrcodeBatchRecordPO.setUpdateTime(nowTime);
        iPropertyRoomInfoDao.save(SqlUtil.durableData(propertyRoomQrcodeBatchRecordPO, PlatformConstants.TABLE_SAVE));
        roomInfoPO.setUpdateTime(nowTime);
        iPropertyRoomInfoDao.update(SqlUtil.durableData(roomInfoPO, PlatformConstants.TABLE_UPDATE));

        //保存线下缴费日志
        PaymentRecordPO paymentRecordPO = new PaymentRecordPO();
        paymentRecordPO.setPaymentId(LogicIdUtil.bussinessId());
        paymentRecordPO.setMealId(paymentRecordDTO.getMealId());
        paymentRecordPO.setRoomId(paymentRecordDTO.getRoomId());
        paymentRecordPO.setProjectId(paymentRecordDTO.getProjectId());
        paymentRecordPO.setRecordType(1);
        paymentRecordPO.setPaymentType(2);
        paymentRecordPO.setPaymentAmount(paymentRecordDTO.getPaymentAmount());
        paymentRecordPO.setPaymentCount(Integer.parseInt(paymentRecordDTO.getPaymentCount()));
        paymentRecordPO.setRemark(paymentRecordDTO.getRemark());
        paymentRecordPO.setStatus(DataStatusEnum.NORMAL.getType());
        paymentRecordPO.setCreateTime(nowTime);
        paymentRecordPO.setCreateUserId(paymentRecordDTO.getLoginUserId());
        paymentRecordPO.setOperateUserId(paymentRecordDTO.getLoginUserId());
        iPropertyRoomInfoDao.save(SqlUtil.durableData(paymentRecordPO, PlatformConstants.TABLE_SAVE));
        Map<String,Object> blackList = new HashMap<>();
        blackList.put("projectId", paymentRecordDTO.getProjectId());
        blackList.put("roomId", paymentRecordDTO.getRoomId());
        List<DeviceBusinessElevatorChangeLogPO> elevatorChanges = new ArrayList<>();
        List<DeviceBusinessEntranceChangeLogPO> entranceChanges = new ArrayList<>();
        DeviceBusinessElevatorChangeLogPO elevatorPo = new DeviceBusinessElevatorChangeLogPO(paymentRecordDTO.getProjectId(), CloudElevatorChangeBusinessEnum.PUSH_BLACK_LIST, JsonUtil.toJSON(blackList));
        elevatorChanges.add(elevatorPo);
        JSONObject pushJs = new JSONObject();
        pushJs.put("data", elevatorChanges);
        //推送云电梯业务指令
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                JsonUtil.toJSON(pushJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);

        //发送云门禁业务指令
        DeviceBusinessEntranceChangeLogPO entrancePO = new DeviceBusinessEntranceChangeLogPO(paymentRecordDTO.getProjectId(), CloudEntranceChangeBusinessEnum.PUSH_BLACK_LIST, JsonUtil.toJSON(blackList));
        entranceChanges.add(entrancePO);
        pushJs.put("data", entranceChanges);
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                JSON.toJSONString(pushJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
        );
    }

    /**
     * <desc>
     *      共享电梯线下退费
     * </desc>
     *
     * @param paymentRecordDTO
     * @author Qiang.S
     * @createDate 2020/07/16
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public void outLineRefund(PaymentRecordDTO paymentRecordDTO) throws Exception {
        Date nowTime = new Date();
        PropertyRoomQrcodeBatchRecordPO propertyRoomQrcodeBatchRecordPO = new PropertyRoomQrcodeBatchRecordPO();
        propertyRoomQrcodeBatchRecordPO.setQrcodeBatchRecordId(LogicIdUtil.bussinessId());
        propertyRoomQrcodeBatchRecordPO.setRoomId(paymentRecordDTO.getRoomId());
        PropertyRoomQrcodeBatchRecordPO roomQrCodeBatch = iPropertyRoomInfoDao.getRoomQrCodeBatch(paymentRecordDTO.getRoomId());
        if (roomQrCodeBatch != null && roomQrCodeBatch.getId() != null) {
            propertyRoomQrcodeBatchRecordPO.setBatch(roomQrCodeBatch.getBatch() + 1);
        } else {
            propertyRoomQrcodeBatchRecordPO.setBatch(1);
        }
        propertyRoomQrcodeBatchRecordPO.setPayCount(StringHandlerUtil.strToIntDef(paymentRecordDTO.getPaymentCount(), 0)* (-1));
        propertyRoomQrcodeBatchRecordPO.setCount(0);
        propertyRoomQrcodeBatchRecordPO.setUsableCount(0);
        propertyRoomQrcodeBatchRecordPO.setStatus(DataStatusEnum.NORMAL.getType());
        propertyRoomQrcodeBatchRecordPO.setCreateTime(nowTime);
        iPropertyRoomInfoDao.save(SqlUtil.durableData(propertyRoomQrcodeBatchRecordPO, PlatformConstants.TABLE_SAVE));

        //保存线下缴费日志
        PaymentRecordPO paymentRecordPO = new PaymentRecordPO();
        paymentRecordPO.setPaymentId(LogicIdUtil.bussinessId());
        paymentRecordPO.setMealId(paymentRecordDTO.getMealId());
        paymentRecordPO.setRoomId(paymentRecordDTO.getRoomId());
        paymentRecordPO.setProjectId(paymentRecordDTO.getProjectId());
        paymentRecordPO.setRecordType(2);
        paymentRecordPO.setPaymentType(2);
        paymentRecordPO.setPaymentAmount(paymentRecordDTO.getPaymentAmount());
        paymentRecordPO.setPaymentCount(Integer.parseInt(paymentRecordDTO.getPaymentCount()));
        paymentRecordPO.setRemark(paymentRecordDTO.getRemark());
        paymentRecordPO.setStatus(DataStatusEnum.NORMAL.getType());
        paymentRecordPO.setCreateTime(nowTime);
        paymentRecordPO.setCreateUserId(paymentRecordDTO.getLoginUserId());
        paymentRecordPO.setOperateUserId(paymentRecordDTO.getLoginUserId());
        iPropertyRoomInfoDao.save(SqlUtil.durableData(paymentRecordPO, PlatformConstants.TABLE_SAVE));
        Map<String,Object> blackList = new HashMap<>();
        blackList.put("projectId", paymentRecordDTO.getProjectId());
        blackList.put("roomId", paymentRecordDTO.getRoomId());
        List<DeviceBusinessElevatorChangeLogPO> elevatorChanges = new ArrayList<>();
        List<DeviceBusinessEntranceChangeLogPO> entranceChanges = new ArrayList<>();
        DeviceBusinessElevatorChangeLogPO elevatorPo = new DeviceBusinessElevatorChangeLogPO(paymentRecordDTO.getProjectId(), CloudElevatorChangeBusinessEnum.PUSH_BLACK_LIST, JsonUtil.toJSON(blackList));
        elevatorChanges.add(elevatorPo);
        JSONObject pushJs = new JSONObject();
        pushJs.put("data", elevatorChanges);
        //推送云电梯业务指令
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                JsonUtil.toJSON(pushJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);

        //发送云门禁业务指令
        DeviceBusinessEntranceChangeLogPO entrancePO = new DeviceBusinessEntranceChangeLogPO(paymentRecordDTO.getProjectId(), CloudEntranceChangeBusinessEnum.PUSH_BLACK_LIST, JsonUtil.toJSON(blackList));
        entranceChanges.add(entrancePO);
        pushJs.put("data", entranceChanges);
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                JSON.toJSONString(pushJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
        );
    }

    /**
     * <desc>
     *    更新房屋信息到数据库.
     * </desc>
     *
     * @param  roomInfoPO 房间信息数据库对象
     * @return 受影响的函数
     * @author LewisLouis
     * @createDate 2018-02-25
     */
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer updateRoomInfoToDB(RoomInfoPO roomInfoPO,PropertyProjectUpdateRoomInfoDTO propertyProjectUpdateRoomInfoDTO) throws Exception{
        //解决房屋类型\房屋户型\房屋状态无法修改为无的问题
        Map<String, Object> map = SqlUtil.durableData(roomInfoPO, PlatformConstants.TABLE_UPDATE);
        List<Map<String, Object>> updates = (List<Map<String, Object>>)map.get("list");
        Map<String,Object> newFileds;
        if (null == propertyProjectUpdateRoomInfoDTO.getRoomType()){
            newFileds = new HashMap<>();
            newFileds.put("columnName","room_type");
            newFileds.put("columnValue",null);
            updates.add(newFileds);
        }
        if (null == propertyProjectUpdateRoomInfoDTO.getRoomLayout()){
            newFileds = new HashMap<>();
            newFileds.put("columnName","room_layout");
            newFileds.put("columnValue",null);
            updates.add(newFileds);
        }
        if (null == propertyProjectUpdateRoomInfoDTO.getRoomStatus()){
            newFileds = new HashMap<>();
            newFileds.put("columnName","room_status");
            newFileds.put("columnValue",null);
            updates.add(newFileds);
        }

        int intRes = iPropertyRoomInfoDao.update(map);

        return intRes;
    }

    /**
     * <desc>
     *      逻辑删除房屋信息(支持按roomId或unitId或buildId进行删除）
     * </desc>
     *
     * @param propertyProjectRemoveRoomInfoDTO 删除房屋信息数据传输对象
     * @return 受影响的行数
     * @author LouisLewis
     * @createDate 2017-09-30
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer removeRoomInfo(PropertyProjectRemoveRoomInfoDTO propertyProjectRemoveRoomInfoDTO) throws Exception {

        //从数据库删除房间信息.(事务保护)
        int intRes = this.removeRoomInfoFromDB(propertyProjectRemoveRoomInfoDTO);

        //删除单个房间时，无条件更新云对讲设备（即使项目没有云对讲，消费者会自行过滤）
        JSONArray jsonArray = new JSONArray();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("roomId",propertyProjectRemoveRoomInfoDTO.getRoomId());
        jsonArray.add(jsonObject);
        DeviceBusinessChangeLogPO deviceBusinessChangeLogPO
                = new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM,jsonArray,propertyProjectRemoveRoomInfoDTO.getProjectId());
        DeviceBusinessElevatorChangeLogPO deviceBusinessElevatorChangeLogPO
                = new DeviceBusinessElevatorChangeLogPO(propertyProjectRemoveRoomInfoDTO.getProjectId(),
                CloudElevatorChangeBusinessEnum.PUSH_ROOM_PWD,jsonArray.toJSONString());
        //云对讲
        List<DeviceBusinessChangeLogPO> deviceBusinessChangeLogPOS = new ArrayList<>();
        deviceBusinessChangeLogPOS.add(deviceBusinessChangeLogPO);
        JSONObject dataJs = new JSONObject();
        dataJs.put("data",deviceBusinessChangeLogPOS);
        messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
        //云电梯
        List<DeviceBusinessElevatorChangeLogPO> deviceElevatorChangeLogPOS = new ArrayList<>();
        deviceElevatorChangeLogPOS.add(deviceBusinessElevatorChangeLogPO);
        dataJs.put("data",deviceElevatorChangeLogPOS);
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                JsonUtil.toJSON(dataJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
        return intRes;
    }


    /**
     * <desc>
     *    从数据库删除房间信息.
     * </desc>
     *
     * @param propertyProjectRemoveRoomInfoDTO 删除房屋信息数据传输对象
     * @return 受影响的行数
     * @author LouisLewis
     * @createDate 2018-02-25
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer removeRoomInfoFromDB(PropertyProjectRemoveRoomInfoDTO propertyProjectRemoveRoomInfoDTO){
        int intRes =  iPropertyRoomInfoDao.remove(propertyProjectRemoveRoomInfoDTO);
        return intRes;
    }

    /**
     * <desc>
     *      分页查询房屋信息
     * </desc>
     *
     * @param propertyProjectGetRoomInfoDTO 分页查询房屋信息数据传输对象
     * @return 分页查询结果对象
     * @author LouisLewis
     * @createDate 2017-10-09
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<PropertyProjectRoomInfoVO> getPage(PropertyProjectGetRoomInfoDTO propertyProjectGetRoomInfoDTO) throws Exception {
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyProjectGetRoomInfoDTO);
        params.put("projectId", propertyProjectGetRoomInfoDTO.getProjectId());

        Page<PropertyProjectRoomInfoVO> page = new Page<>();
        page.getPage().setPageSize(propertyProjectGetRoomInfoDTO.getPageSize());
        page.getPage().setCurrentPage(propertyProjectGetRoomInfoDTO.getCurrentPage());
        params.put("startSlip", page.getPage().getStartSlip());
        params.put("pageSize", page.getPage().getPageSize());
        //填充返回数据集
        List<PropertyProjectRoomInfoVO> propertyProjectRoomInfoVOS = iPropertyRoomInfoDao.getPageList(params);
        page.setRows(propertyProjectRoomInfoVOS, iPropertyRoomInfoDao.getRecordCount(params));
        return page;
    }

    /**
     * <desc>
     *      获取指定单元下的房屋简单信息（房屋id ,房屋名称）列表
     * </desc>
     *
     * @param propertyProjectGetRoomSimpleInfoDTO 查询房屋简单信息（房屋ID，房屋名称）数据传输对象
     * @return 房屋简单信息（房屋id ,房屋名称）列表
     * @author LewisLouis
     * @createDate 2017-10-09
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<PropertyProjectRoomSimpleInfoVO> getPageRoomSimpleInfoList(PropertyProjectGetRoomSimpleInfoDTO propertyProjectGetRoomSimpleInfoDTO) throws Exception {
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyProjectGetRoomSimpleInfoDTO);
        Page<PropertyProjectRoomSimpleInfoVO> page = new Page<>();
        page.getPage().setPageSize(propertyProjectGetRoomSimpleInfoDTO.getPageSize());
        page.getPage().setCurrentPage(propertyProjectGetRoomSimpleInfoDTO.getCurrentPage());
        params.put("startSlip", page.getPage().getStartSlip());
        params.put("pageSize", page.getPage().getPageSize());
        //填充返回数据集
        List<PropertyProjectRoomSimpleInfoVO> propertyProjectRoomSimpleInfoVOS = iPropertyRoomInfoDao.getPageRoomSimpleInfoList(params);
        page.setRows(propertyProjectRoomSimpleInfoVOS, iPropertyRoomInfoDao.getRecordCount(params));

        return page;
    }

    /**
     * <desc>
     *      查询指定单元下的排除部分房间的其它所有房屋简单信息（房屋ID，房屋名称）数据传输对象
     * </desc>
     *
     * @param propertyProjectGetRoomSimpleInfoExcludeIdsDTO 查询指定单元下的排除部分房间的其它所有房屋简单信息（房屋ID，房屋名称）数据传输对象
     * @return 房屋简单信息（房屋id ,房屋名称）列表
     * @createDate 2017-10-24
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Map<String,Object> getRoomSimpleInfoExcludeIds(PropertyProjectGetRoomSimpleInfoExcludeIdsDTO propertyProjectGetRoomSimpleInfoExcludeIdsDTO) throws Exception {

        Map<String, Object> params = new HashMap<>();
        params.put("unitId", propertyProjectGetRoomSimpleInfoExcludeIdsDTO.getUnitId());
        Page<PropertyProjectRoomSimpleInfoVO> page = new Page<>();
        if (StringUtils.isBlank(propertyProjectGetRoomSimpleInfoExcludeIdsDTO.getPageSize())){
            page.getPage().setPageSize(String.valueOf(PlatformConstants.MAX_ROOM_NUM));
        } else{
            page.getPage().setPageSize(propertyProjectGetRoomSimpleInfoExcludeIdsDTO.getPageSize());
        }
        if (StringUtils.isBlank(propertyProjectGetRoomSimpleInfoExcludeIdsDTO.getCurrentPage())){
            page.getPage().setCurrentPage("1");
        } else{
            page.getPage().setCurrentPage(propertyProjectGetRoomSimpleInfoExcludeIdsDTO.getCurrentPage());
        }

        params.put("startSlip", page.getPage().getStartSlip());
        params.put("pageSize", page.getPage().getPageSize());
        //填充返回数据集
        List<PropertyProjectRoomSimpleInfoVO> pageRoomSimpleInfoList = iPropertyRoomInfoDao.getPageRoomSimpleInfoList(params);
        Map<String,Object> result = new HashMap<>();
        result.put("pageSize",pageRoomSimpleInfoList.size());
        //遍历查询结果集，排除RoomIds
        if ((pageRoomSimpleInfoList != null) && (!pageRoomSimpleInfoList.isEmpty())){
            Iterator<PropertyProjectRoomSimpleInfoVO> infoVOIterator = pageRoomSimpleInfoList.iterator();
            while (infoVOIterator.hasNext()) {
                PropertyProjectRoomSimpleInfoVO propertyProjectRoomSimpleInfoVO = infoVOIterator.next();
                List<String> excludeRoomIds = propertyProjectGetRoomSimpleInfoExcludeIdsDTO.getExcludeRoomIds();
                if (excludeRoomIds.contains(propertyProjectRoomSimpleInfoVO.getRoomId())) {
                    infoVOIterator.remove();
                }
            }
        }
        result.put("list",pageRoomSimpleInfoList);
        return result;
    }

    /**
     * <desc>
     *      精确查询，获取单个房屋信息
     * </desc>
     *
     * @param propertyProjectGetRoomInfoDTO 查询房屋信息数据传输对象
     * @return 按创建时间降序排列，首个符合查询条件的房屋信息
     * @author LouisLewis
     * @createDate 2017-10-09
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public PropertyProjectRoomInfoVO getOneRoomInfo(PropertyProjectGetRoomInfoDTO propertyProjectGetRoomInfoDTO) {
        RoomInfoPO inRoomInfoPO = new RoomInfoPO();
        BeanUtils.copyProperties(propertyProjectGetRoomInfoDTO, inRoomInfoPO);
        PropertyProjectRoomInfoVO oneRoomInfo = iPropertyRoomInfoDao.getOneRoomInfo(inRoomInfoPO);
        PropertyRoomQrcodeBatchRecordPO propertyRoomQrcodeBatchRecordPO  = iPropertyRoomInfoDao.getRoomQrCodeBatch(propertyProjectGetRoomInfoDTO.getRoomId());
        if (oneRoomInfo != null) {
            if (propertyRoomQrcodeBatchRecordPO != null && propertyRoomQrcodeBatchRecordPO.getUsableCount() != null) {
                oneRoomInfo.setUsableTimes(propertyRoomQrcodeBatchRecordPO.getUsableCount().toString());
            } else {
                oneRoomInfo.setUsableTimes("0");
            }
        }
        return oneRoomInfo;
    }

    /**
     * <desc>
     * 精确查询，快速获取单个房间简单信息
     * </desc>
     *
     * @param propertyProjectGetRoomInfoDTO 查询房间信息数据传输对象
     * @return 不进行排序，返回首个符合查询条件的房间信息
     * @author LouisLewis
     * @createDate 2018-02-06
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public RoomInfoPO getOneSimpleRoomInfo(PropertyProjectGetRoomInfoDTO propertyProjectGetRoomInfoDTO) {
        RoomInfoPO inRoomInfoPO = new RoomInfoPO();
        BeanUtils.copyProperties(propertyProjectGetRoomInfoDTO, inRoomInfoPO);
        return iPropertyRoomInfoDao.getOneSimpleRoomInfo(inRoomInfoPO);
    }

    /**
     * <desc>
     * 获取当前单元楼层下可用的房号和访客呼叫码，用于在添加房屋时提示用户。
     * </desc>
     *
     * @param getMinAvaliableRoomInfoDTO  获取最小可用房号和访客呼叫码查询对象
     * @return 当前单元楼层下可用的房间信息
     * @author LewisLouis
     * @createDate 2018-01-15
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public PropertyProjectMinAvaliableRoomInfoVO getMinAvaliableRoomInfo(PropertyProjectGetMinAvaliableRoomInfoDTO getMinAvaliableRoomInfoDTO) {
        String newRoomNum = "";
        String newRoomAlias = "";
        Integer floorNo = getMinAvaliableRoomInfoDTO.getFloorNo();

        //0号楼层，云对讲管理中心房间及呼叫代号
        if ((null != floorNo) && (floorNo == 0)){
            newRoomNum = PlatformConstants.CENTER_CALL_CODE;
            newRoomAlias = PlatformConstants.CENTER_CALL_CODE;
            PropertyProjectMinAvaliableRoomInfoVO roomInfoVO = new PropertyProjectMinAvaliableRoomInfoVO();
            roomInfoVO.setRoomNum(newRoomNum);
            roomInfoVO.setRoomAlias(newRoomAlias);
            return roomInfoVO;
        }

        //获取当前单元下的所有房屋
        List<PropertyProjectRoomSimpleInfoExVO> roomSimpleInfoExVOS = iPropertyRoomInfoDao.getRoomInfoByUnitId(getMinAvaliableRoomInfoDTO.getUnitId());

        List<String> roomNumsInUnit = new ArrayList<>();  //当前单元下已存在的所有房号列表
        List<String> roomAliasInUnit = new ArrayList<>();//当前单元下已存在的所有访客呼叫码列表
        for (int roomIndex = 0; roomIndex < roomSimpleInfoExVOS.size(); roomIndex++) {
            PropertyProjectRoomSimpleInfoExVO oneRoomInfo = roomSimpleInfoExVOS.get(roomIndex);
            roomNumsInUnit.add(oneRoomInfo.getRoomNum());
            roomAliasInUnit.add(oneRoomInfo.getRoomAlias());
        }


        //先生成房间号
        if (StringUtils.isBlank(getMinAvaliableRoomInfoDTO.getRoomNum())){
            //先基于本楼层生成房间号
            for (int roomIndex = PlatformConstants.ONE_FLOOR_MIN_ROOM_NUM; roomIndex <  PlatformConstants.ONE_FLOOR_MAX_ROOM_NUM; roomIndex++) {
                String oneRoomNum = String.format("%02d%02d", floorNo,roomIndex);
                if (roomNumsInUnit.indexOf(oneRoomNum) < 0) {
                    newRoomNum = oneRoomNum;
                    break;
                }
            }

            //如果本楼层的默认房间号已占满，则在这个单元中查找未被占用的最小房间号
            if (StringUtils.isBlank(newRoomNum)) {
                for (int roomNum = PlatformConstants.MIN_ROOM_NUM; roomNum < PlatformConstants.MAX_ROOM_NUM; roomNum++) {
                    String oneRoomNum = String.format("%04d", roomNum);
                    if (roomNumsInUnit.indexOf(oneRoomNum) < 0) {
                        newRoomNum = oneRoomNum;
                        break;
                    }
                }
                if (StringUtils.isBlank(newRoomNum)) {
                    System.out.println(String.format("未找到可用的房号,相关信息:%s", JSON.toJSONString(getMinAvaliableRoomInfoDTO)));
                }
            }
        } else {
            newRoomNum = getMinAvaliableRoomInfoDTO.getRoomNum();
        }


        //优先基于房间号生成访客呼叫码
        if (StringUtils.isNotBlank(newRoomNum)){
            String defaultRoomAlias = newRoomNum.replaceAll("^(0+)", ""); ;
            if (roomAliasInUnit.indexOf(defaultRoomAlias) < 0) {
                newRoomAlias = defaultRoomAlias;
            }
        }

        //再基于本楼层生成访客呼叫码
        if (StringUtils.isBlank(newRoomAlias)) {
            for (int roomIndex = PlatformConstants.ONE_FLOOR_MIN_ROOM_NUM; roomIndex <  PlatformConstants.ONE_FLOOR_MAX_ROOM_NUM; roomIndex++) {
                String oneRoomAlias= String.format("%d%02d", floorNo,roomIndex);
                if (roomAliasInUnit.indexOf(oneRoomAlias) < 0) {
                    newRoomAlias = oneRoomAlias;
                    break;
                }
            }
        }

        //如果本楼层的默认访客呼叫码已占满，则在这个单元中查找未被占用的最小访客呼叫码
        if (StringUtils.isBlank(newRoomAlias)) {
            for (int roomAlias = PlatformConstants.MIN_ROOM_ALIAS; roomAlias < PlatformConstants.MAX_ROOM_ALIAS; roomAlias++) {
                String oneRoomAlias = String.format("%d", roomAlias);
                if (roomAliasInUnit.indexOf(oneRoomAlias) < 0) {
                    newRoomAlias = oneRoomAlias;
                    break;
                }
            }
        }
        if (StringUtils.isBlank(newRoomAlias)) {
            System.out.println(String.format("未找到可用的访客呼叫码,相关信息:%s", JSON.toJSONString(getMinAvaliableRoomInfoDTO)));
        }

        PropertyProjectMinAvaliableRoomInfoVO roomInfoVO = new PropertyProjectMinAvaliableRoomInfoVO();
        roomInfoVO.setRoomNum(newRoomNum);
        roomInfoVO.setRoomAlias(newRoomAlias);
        return roomInfoVO;

    }

    /**
     * <desc>
     *    查询房屋列表
     * </desc>
     *
     * @param userId  用户编号
     * @param projectId 项目编号
     * @return 用户的房间信息
     * @author Qiang.S
     * @createDate 2018-11-20
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<MiniProgramPassRoomListVO> myRoomsInfoALL(String userId, String projectId) {
        return iPropertyRoomInfoDao.myRoomsInfo(userId,projectId);
    }

    /**
     * <desc>
     *    查询业主房屋列表
     * </desc>
     *
     * @param userId  用户编号
     * @param projectId 项目编号
     * @return 用户的房间信息
     * @author Qiang.S
     * @createDate 2018-11-20
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<MiniProgramPassRoomListVO> myRoomsInfo(String userId, String projectId) {
        List<MiniProgramPassRoomListVO> rooms = iPropertyRoomInfoDao.myRoomsInfoOther(userId,projectId);
        Set<String> roomIds = new HashSet<>();
        rooms.forEach(room->{
            roomIds.add(room.getRoomId());
        });
        //获取房间剩余通行次数
        if(roomIds.size() > 0) {
            List<Map<String, Object>> lastCount = iAppRoomDao.getRoomLastCountByRoomId(roomIds);
            rooms.forEach(room -> {
                Optional<Map<String, Object>> optional = lastCount.stream().filter(map -> map.get("roomId").toString().equals(room.getRoomId())).findFirst();
                if (optional.isPresent()) {
                    room.setLastPassCount(optional.get().get("usableCount").toString());
                    room.setChargeMode(optional.get().get("chargeMode").toString());
                } else {
                    room.setChargeMode("1");
                    room.setLastPassCount("0");
                }
            });
        }else{
            rooms.forEach(room -> {
                room.setChargeMode("1");
                room.setLastPassCount("0");
            });
        }
        return rooms;
    }

    /**
     * <desc>
     *    根据手机号查询用户UserId
     * </desc>
     *
     * @param phoneNum  手机号
     * @return 用户的userId
     * @author Juguang.S
     * @createDate 2019-04-25
     */
    @Override
    public String getUserIdByPhone(String phoneNum) {
        return iPropertyRoomInfoDao.getUserIdByPhone(phoneNum);
    }

    /**
     * <desc>
     *      根据数据传输对象返回房屋信息数据库实体对象，用于保存到数据库
     * </desc>
     *
     * @param propertyProjectSaveRoomInfoDTO 添加房屋信息数据传输对象
     * @return 房屋信息数据库实体对象
     * @author LewisLouis
     * @createDate 2017-09-29
     */
    private RoomInfoPO getRoomInfoBySaveDTO(PropertyProjectSaveRoomInfoDTO propertyProjectSaveRoomInfoDTO) {
        RoomInfoPO roomInfoPO = new RoomInfoPO();
        BeanUtils.copyProperties(propertyProjectSaveRoomInfoDTO, roomInfoPO);
        String roomId = LogicIdUtil.bussinessId();
        roomInfoPO.setRoomId(roomId);
        Date createTime = new Date();
        roomInfoPO.setCreateTime(createTime);
        roomInfoPO.setUpdateTime(createTime);
        roomInfoPO.setStatus(DataStatusEnum.NORMAL.getType());
        return roomInfoPO;
    }

    /**
     * <desc>
     *      查询所有房屋
     * </desc>
     *
     * @param projectId 项目编号
     * @return 项目下所有房屋
     * @author wangzhi
     * @createDate 2019/01/07
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<PropertyProjectRoomInfoVO> getAllRoomInfoByProjectId(String projectId) throws Exception {
        return iPropertyRoomInfoDao.getAllRoomInfoByProjectId(projectId);
    }
}
